﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using WindowsFormsApplication1;
using _2013_ece_csharp_snake;
using System.Diagnostics;
using System.Windows.Forms;

public class ConnexionReceiveMulti
{
    private WindowsFormsApplication1.FormDemo form;
    private EventWaitHandle eventFin;
    private EventWaitHandle eventSend;

    private ConnectionInformation coInf;


    public ConnexionReceiveMulti(WindowsFormsApplication1.FormDemo form, EventWaitHandle eventF, EventWaitHandle eventS, TcpListener tcpListener, ConnectionInformation coInf)
    {
        this.form = form;
        this.eventFin = eventF;
        this.eventSend = eventS;

        this.coInf = coInf;

        Thread serverThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
        serverThread.IsBackground = true;
        serverThread.Start(null);

    }

    private void initiateCommunication()
    {

    }

    private void HandleClientComm(object udpClient)
    {
        Socket listenSocket = (Socket)udpClient;
        EndPoint remote_ep = new IPEndPoint(IPAddress.Any, 0);
        bool isHost;

        // Socket Creation
        listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
        // Bind to port 50000
        listenSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));
        // Ask to receive from a specific Multicast IP Address
        listenSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.1.1.42")));


        byte[] message = new byte[4096];
        int bytesRead;
        ASCIIEncoding encoder = new ASCIIEncoding();
        String s;
        String[] temp;
        String[] encap;

        IPHostEntry host;
        string [] localIP;
        host = Dns.GetHostEntry(Dns.GetHostName());
        localIP = new String[host.AddressList.Length];
        bool sameIP = false;

        for (int i=0; i<host.AddressList.Length; i++)
        {
            if (host.AddressList[i].AddressFamily.ToString() == "InterNetwork")
            {
                localIP[i] = host.AddressList[i].ToString();
            }
        }
        coInf.myIP = localIP[0];

        while (!eventFin.WaitOne(10))
        {

            bytesRead = listenSocket.ReceiveFrom(message, ref remote_ep);
            s = Encoding.UTF8.GetString(message, 0, bytesRead);

            encap = s.Split(']');
            temp = remote_ep.ToString().Split(':');

            sameIP = false;
            for (int i = 0; i < localIP.Length; i++)
                if (localIP[i] == temp[0])
                    sameIP = true;

            if (sameIP == false && coInf.connected == true)
            {
                if (encap[0] == "[text")
                {
                    form.receiveMessage("-> " + temp[0] + " : " + (Encoding.UTF8.GetString(message, 0, bytesRead)));
                }
                else if (encap[0] == "[data")
                {
                    DataSend ds = DataSend.DeserializeFromString<DataSend>(encap[1]);

                    form.receiveMessage("-> " + temp[0] + " : " + ds.headX);
                    form.getMultiGame().Snake.Data = ds;

                    if (ds.newWall == true)
                    {
                        form.getGameZone().NewWall = true;
                        form.getGameZone().Wall = ds.wall;
                    }

                }
                else if (encap[0] == "[wall")
                {

                }
            }

            if (sameIP == false && encap[0] == "[ping")
            {
                isHost = false;
                for (int i = 0; i < coInf.hostsIP.Count; i++)
                    if (coInf.hostsIP[i] == temp[0])
                        isHost = true;

                if (isHost == false)
                {
                    coInf.hostsIP.Add(temp[0]);
                    coInf.hostsName.Add(encap[1]);
                }
            }
            else if (sameIP == false && encap[0] == "[ConnectionDemand")
            {
                // if I am the target of the demand 
                isHost = false;
                

                if (encap[1] == localIP[0])
                {
                    if (System.Windows.Forms.MessageBox.Show( encap[2] + " (" + temp[0] + ") wants to play with you. Do you ?", "Connection asked", System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                    {
                        coInf.eventConfirmation.Set();
                        coInf.connected = true;
                    }
                }
            }
            else if (sameIP == false && encap[0] == "[ConnectionConfirmation")
            {
                coInf.connected = true;
                System.Windows.Forms.MessageBox.Show("Confirmation received from " + encap[2]);
            }
            
        }

        listenSocket.Close();
    }

}
